#include "viml/builtin_math.h"
#include "viml/value.h"
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <sstream>
#include <iomanip>
#include <stdexcept>
#include <limits>
#include <string>
#include <cctype>
#include <vector>

namespace viml {

// ========================================
// 数学运算函数组
// ========================================

Value abs_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("abs() requires exactly 1 argument");
    }
    
    const Value& arg = args[0];
    
    // 检查参数类型并计算绝对值
    if (arg.is_number()) {
        double value = arg.as_number();
        if (value == std::floor(value) && value >= std::numeric_limits<int64_t>::min() && 
            value <= std::numeric_limits<int64_t>::max()) {
            // 如果是整数，返回整数类型
            return Value::make_number(std::abs(static_cast<int64_t>(value)));
        } else {
            // 如果是浮点数，返回浮点数类型
            return Value::make_float(std::abs(value));
        }
    } else if (arg.is_float()) {
        return Value::make_float(std::abs(arg.as_float()));
    } else {
        throw std::runtime_error("abs() argument must be a number");
    }
}

Value sqrt_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("sqrt() requires exactly 1 argument");
    }
    
    const Value& arg = args[0];
    double value;
    
    // 获取数值
    if (arg.is_number()) {
        value = arg.as_number();
    } else if (arg.is_float()) {
        value = arg.as_float();
    } else {
        throw std::runtime_error("sqrt() argument must be a number");
    }
    
    // 检查输入值必须非负
    if (value < 0) {
        throw std::runtime_error("sqrt() argument must be non-negative");
    }
    
    return Value::make_float(std::sqrt(value));
}

Value pow_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 2) {
        throw std::runtime_error("pow() requires exactly 2 arguments");
    }
    
    const Value& base_arg = args[0];
    const Value& exp_arg = args[1];
    double base, exponent;
    
    // 获取底数
    if (base_arg.is_number()) {
        base = base_arg.as_number();
    } else if (base_arg.is_float()) {
        base = base_arg.as_float();
    } else {
        throw std::runtime_error("pow() first argument must be a number");
    }
    
    // 获取指数
    if (exp_arg.is_number()) {
        exponent = exp_arg.as_number();
    } else if (exp_arg.is_float()) {
        exponent = exp_arg.as_float();
    } else {
        throw std::runtime_error("pow() second argument must be a number");
    }
    
    return Value::make_float(std::pow(base, exponent));
}

Value exp_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("exp() requires exactly 1 argument");
    }
    
    const Value& arg = args[0];
    double value;
    
    // 获取数值
    if (arg.is_number()) {
        value = arg.as_number();
    } else if (arg.is_float()) {
        value = arg.as_float();
    } else {
        throw std::runtime_error("exp() argument must be a number");
    }
    
    return Value::make_float(std::exp(value));
}

Value log_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("log() requires exactly 1 argument");
    }
    
    const Value& arg = args[0];
    double value;
    
    // 获取数值
    if (arg.is_number()) {
        value = arg.as_number();
    } else if (arg.is_float()) {
        value = arg.as_float();
    } else {
        throw std::runtime_error("log() argument must be a number");
    }
    
    // 检查输入值必须为正数
    if (value <= 0) {
        throw std::runtime_error("log() argument must be positive");
    }
    
    return Value::make_float(std::log(value));
}

Value log10_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("log10() requires exactly 1 argument");
    }
    
    const Value& arg = args[0];
    double value;
    
    // 获取数值
    if (arg.is_number()) {
        value = arg.as_number();
    } else if (arg.is_float()) {
        value = arg.as_float();
    } else {
        throw std::runtime_error("log10() argument must be a number");
    }
    
    // 检查输入值必须为正数
    if (value <= 0) {
        throw std::runtime_error("log10() argument must be positive");
    }
    
    return Value::make_float(std::log10(value));
}

Value sin_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("sin() requires exactly 1 argument");
    }
    
    const Value& arg = args[0];
    double value;
    
    // 获取数值
    if (arg.is_number()) {
        value = arg.as_number();
    } else if (arg.is_float()) {
        value = arg.as_float();
    } else {
        throw std::runtime_error("sin() argument must be a number");
    }
    
    return Value::make_float(std::sin(value));
}

Value cos_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("cos() requires exactly 1 argument");
    }
    
    const Value& arg = args[0];
    double value;
    
    // 获取数值
    if (arg.is_number()) {
        value = arg.as_number();
    } else if (arg.is_float()) {
        value = arg.as_float();
    } else {
        throw std::runtime_error("cos() argument must be a number");
    }
    
    return Value::make_float(std::cos(value));
}

Value tan_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("tan() requires exactly 1 argument");
    }
    
    const Value& arg = args[0];
    double value;
    
    // 获取数值
    if (arg.is_number()) {
        value = arg.as_number();
    } else if (arg.is_float()) {
        value = arg.as_float();
    } else {
        throw std::runtime_error("tan() argument must be a number");
    }
    
    return Value::make_float(std::tan(value));
}

// ========================================
// 数值转换函数组
// ========================================

Value float2nr_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("float2nr() requires exactly 1 argument");
    }
    
    const Value& arg = args[0];
    double value;
    
    // 获取数值
    if (arg.is_number()) {
        value = arg.as_number();
    } else if (arg.is_float()) {
        value = arg.as_float();
    } else {
        throw std::runtime_error("float2nr() argument must be a number");
    }
    
    // 截断小数部分转为整数
    return Value::make_number(static_cast<int64_t>(std::trunc(value)));
}

Value str2nr_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("str2nr() requires exactly 1 argument");
    }
    
    const Value& arg = args[0];
    
    // 检查参数类型
    if (!arg.is_string()) {
        throw std::runtime_error("str2nr() argument must be a string");
    }
    
    const std::string& str = arg.as_string();
    
    // 提取数字部分，忽略非数字字符
    std::string num_str;
    bool found_digit = false;
    bool negative = false;
    
    for (size_t i = 0; i < str.length(); ++i) {
        char c = str[i];
        
        if (std::isspace(c) && !found_digit) {
            // 跳过前导空白
            continue;
        }
        
        if (c == '-' && !found_digit && num_str.empty()) {
            // 处理负号
            negative = true;
            continue;
        }
        
        if (c == '+' && !found_digit && num_str.empty()) {
            // 处理正号
            continue;
        }
        
        if (std::isdigit(c)) {
            num_str += c;
            found_digit = true;
        } else if (found_digit) {
            // 遇到非数字字符且已经找到数字，停止解析
            break;
        }
    }
    
    if (num_str.empty()) {
        return Value::make_number(0);
    }
    
    try {
        int64_t result = std::stoll(num_str);
        return Value::make_number(negative ? -result : result);
    } catch (const std::exception&) {
        return Value::make_number(0);
    }
}

Value str2float_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("str2float() requires exactly 1 argument");
    }
    
    const Value& arg = args[0];
    
    // 检查参数类型
    if (!arg.is_string()) {
        throw std::runtime_error("str2float() argument must be a string");
    }
    
    const std::string& str = arg.as_string();
    
    try {
        // 支持科学计数法
        double result = std::stod(str);
        return Value::make_float(result);
    } catch (const std::exception&) {
        return Value::make_float(0.0);
    }
}

Value string_math_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("string() requires exactly 1 argument");
    }
    
    const Value& arg = args[0];
    
    // 数字转字符串，保持原始精度表示
    if (arg.is_number()) {
        double value = arg.as_number();
        if (value == std::floor(value) && std::abs(value) < 1e15) {
            // 如果是整数值，显示为整数
            return Value::string(std::to_string(static_cast<int64_t>(value)));
        } else {
            // 否则显示为浮点数
            return Value::string(std::to_string(value));
        }
    } else if (arg.is_float()) {
        return Value::string(std::to_string(arg.as_float()));
    } else {
        throw std::runtime_error("string() argument must be a number");
    }
}

// ========================================
// 四舍五入与截断函数组
// ========================================

Value round_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("round() requires exactly 1 argument");
    }
    
    const Value& arg = args[0];
    double value;
    
    // 获取数值
    if (arg.is_number()) {
        value = arg.as_number();
    } else if (arg.is_float()) {
        value = arg.as_float();
    } else {
        throw std::runtime_error("round() argument must be a number");
    }
    
    return Value::make_float(std::round(value));
}

Value ceil_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("ceil() requires exactly 1 argument");
    }
    
    const Value& arg = args[0];
    double value;
    
    // 获取数值
    if (arg.is_number()) {
        value = arg.as_number();
    } else if (arg.is_float()) {
        value = arg.as_float();
    } else {
        throw std::runtime_error("ceil() argument must be a number");
    }
    
    return Value::make_float(std::ceil(value));
}

Value floor_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("floor() requires exactly 1 argument");
    }
    
    const Value& arg = args[0];
    double value;
    
    // 获取数值
    if (arg.is_number()) {
        value = arg.as_number();
    } else if (arg.is_float()) {
        value = arg.as_float();
    } else {
        throw std::runtime_error("floor() argument must be a number");
    }
    
    return Value::make_float(std::floor(value));
}

Value trunc_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("trunc() requires exactly 1 argument");
    }
    
    const Value& arg = args[0];
    double value;
    
    // 获取数值
    if (arg.is_number()) {
        value = arg.as_number();
    } else if (arg.is_float()) {
        value = arg.as_float();
    } else {
        throw std::runtime_error("trunc() argument must be a number");
    }
    
    return Value::make_float(std::trunc(value));
}

// ========================================
// 随机数与时间函数组
// ========================================

Value rand_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 0) {
        throw std::runtime_error("rand() requires no arguments");
    }
    
    return Value::make_number(std::rand());
}

Value srand_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("srand() requires exactly 1 argument");
    }
    
    const Value& arg = args[0];
    
    // 检查参数类型
    if (!arg.is_number()) {
        throw std::runtime_error("srand() argument must be a number");
    }
    
    unsigned int seed = static_cast<unsigned int>(arg.as_number());
    std::srand(seed);
    
    return Value::nil();
}

Value localtime_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 0) {
        throw std::runtime_error("localtime() requires no arguments");
    }
    
    // 获取当前时间
    std::time_t now = std::time(nullptr);
    std::tm* local_tm = std::localtime(&now);
    
    if (!local_tm) {
        throw std::runtime_error("Failed to get local time");
    }
    
    // 创建结果列表: [年,月,日,时,分,秒,周几,年内天数]
    Value result_list = Value::list();
    auto& list_elements = result_list.as_list();
    
    list_elements.push_back(Value::make_number(1900 + local_tm->tm_year)); // 年
    list_elements.push_back(Value::make_number(1 + local_tm->tm_mon));     // 月 (1-12)
    list_elements.push_back(Value::make_number(local_tm->tm_mday));        // 日
    list_elements.push_back(Value::make_number(local_tm->tm_hour));        // 时
    list_elements.push_back(Value::make_number(local_tm->tm_min));         // 分
    list_elements.push_back(Value::make_number(local_tm->tm_sec));         // 秒
    list_elements.push_back(Value::make_number(local_tm->tm_wday));        // 周几 (0-6, 0=周日)
    list_elements.push_back(Value::make_number(1 + local_tm->tm_yday));    // 年内天数 (1-366)
    
    return result_list;
}

Value strftime_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("strftime() requires exactly 1 argument");
    }
    
    const Value& arg = args[0];
    
    // 检查参数类型
    if (!arg.is_string()) {
        throw std::runtime_error("strftime() argument must be a string");
    }
    
    const std::string& format = arg.as_string();
    
    // 获取当前时间
    std::time_t now = std::time(nullptr);
    std::tm* local_tm = std::localtime(&now);
    
    if (!local_tm) {
        throw std::runtime_error("Failed to get local time");
    }
    
    // 格式化时间字符串
    char buffer[1024];
    std::size_t result = std::strftime(buffer, sizeof(buffer), format.c_str(), local_tm);
    
    if (result == 0) {
        throw std::runtime_error("strftime() formatting failed");
    }
    
    return Value::string(std::string(buffer));
}

// ========================================
// 其他实用函数组
// ========================================

Value fmod_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 2) {
        throw std::runtime_error("fmod() requires exactly 2 arguments");
    }
    
    const Value& dividend_arg = args[0];
    const Value& divisor_arg = args[1];
    double dividend, divisor;
    
    // 获取被除数
    if (dividend_arg.is_number()) {
        dividend = dividend_arg.as_number();
    } else if (dividend_arg.is_float()) {
        dividend = dividend_arg.as_float();
    } else {
        throw std::runtime_error("fmod() first argument must be a number");
    }
    
    // 获取除数
    if (divisor_arg.is_number()) {
        divisor = divisor_arg.as_number();
    } else if (divisor_arg.is_float()) {
        divisor = divisor_arg.as_float();
    } else {
        throw std::runtime_error("fmod() second argument must be a number");
    }
    
    // 检查除数不为零
    if (divisor == 0.0) {
        throw std::runtime_error("fmod() division by zero");
    }
    
    return Value::make_float(std::fmod(dividend, divisor));
}

Value hex_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("hex() requires exactly 1 argument");
    }
    
    const Value& arg = args[0];
    
    // 检查参数类型
    if (!arg.is_number()) {
        throw std::runtime_error("hex() argument must be a number");
    }
    
    int64_t value = static_cast<int64_t>(arg.as_number());
    
    // 转换为十六进制字符串（小写，无前缀）
    std::stringstream ss;
    ss << std::hex << value;
    
    return Value::string(ss.str());
}

Value oct_builtin(const std::vector<Value>& args) {
    // 检查参数数量
    if (args.size() != 1) {
        throw std::runtime_error("oct() requires exactly 1 argument");
    }
    
    const Value& arg = args[0];
    
    // 检查参数类型
    if (!arg.is_number()) {
        throw std::runtime_error("oct() argument must be a number");
    }
    
    int64_t value = static_cast<int64_t>(arg.as_number());
    
    // 转换为八进制字符串（无前缀）
    std::stringstream ss;
    ss << std::oct << value;
    
    return Value::string(ss.str());
}

} // namespace viml